package com.siashan.toolkit.oss.provider;

import com.alibaba.fastjson2.JSON;
import com.siashan.toolkit.oss.aliyun.core.AliyunOssConfig;
import com.siashan.toolkit.oss.aliyun.core.AliyunOssStorageService;
import com.siashan.toolkit.oss.aws.core.AwsS3Config;
import com.siashan.toolkit.oss.aws.core.AwsS3StorageService;
import com.siashan.toolkit.oss.core.OssResult;
import com.siashan.toolkit.oss.core.OssStorageService;
import com.siashan.toolkit.oss.core.enums.OssChannel;
import com.siashan.toolkit.oss.core.exception.ToolkitOssException;
import com.siashan.toolkit.oss.minio.core.MinioOssConfig;
import com.siashan.toolkit.oss.minio.core.MinioOssStorageService;
import com.siashan.toolkit.oss.qcloud.core.QCloudOssStorageService;
import com.siashan.toolkit.oss.qcloud.core.QcloudOssConfig;
import com.siashan.toolkit.oss.qiniu.core.QiniuOssConfig;
import com.siashan.toolkit.oss.qiniu.core.QiniuOssStorageService;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * OSS服务商
 *
 * @author siashan
 * @date 2023/6/6
 * @since v1.2.3
 **/
@Slf4j
public class OssProvider {

    /**
     * Oss存储服务执行器池
     */
    private static ArrayList<OssStorageService> executorPool = new ArrayList<>();


    /**
     * 初始化短信渠道
     *
     * @param channelList 短信渠道列表
     */
    public static void init(List<OssProviderChannel> channelList) {
        executorPool.clear();
        if (null != channelList && !channelList.isEmpty()) {
            for (OssProviderChannel channel : channelList) {
                OssStorageService executor = null;
                OssChannel smsChannel = channel.getChannel();
                switch (smsChannel) {
                    case QINIU:
                        QiniuOssConfig qiniuOssConfig = JSON.parseObject(channel.getConfig(), QiniuOssConfig.class);
                        executor = new QiniuOssStorageService(qiniuOssConfig);
                        break;
                    case ALIYUN:
                        AliyunOssConfig aliyunOssConfig = JSON.parseObject(channel.getConfig(), AliyunOssConfig.class);
                        executor = new AliyunOssStorageService(aliyunOssConfig);
                        break;
                    case QCLOUD:
                        QcloudOssConfig qcloudOssConfig = JSON.parseObject(channel.getConfig(), QcloudOssConfig.class);
                        executor = new QCloudOssStorageService(qcloudOssConfig);
                        break;
                    case MinIO:
                        MinioOssConfig minioOssConfig = JSON.parseObject(channel.getConfig(), MinioOssConfig.class);
                        executor = new MinioOssStorageService(minioOssConfig);
                        break;
                    case AWSS3:
                        AwsS3Config awsS3Config = JSON.parseObject(channel.getConfig(), AwsS3Config.class);
                        executor = new AwsS3StorageService(awsS3Config);
                        break;
                    default:
                        break;
                }
                if (null != executor) {
                    executor.setChannelCode(channel.getChannelCode());
                    executorPool.add(executor);
                }
            }
        }
    }


    /**
     * 文件上传
     *
     * @param data    文件字节数组
     * @param path    文件路径，包含文件名
     * @return        文件上传结果
     */
    public static OssResult upload(byte[] data, String path){
       return getExecutor().upload(data,path);
    }

    /**
     * 文件上传
     *
     * @param data     文件字节数组
     * @param suffix   文件后缀
     * @return         文件上传结果
     */
    public static OssResult uploadSuffix(byte[] data, String suffix){
        return getExecutor().uploadSuffix(data,suffix);
    }

    /**
     * 文件上传
     *
     * @param inputStream   字节流
     * @param path          文件路径，包含文件名
     * @return              文件上传结果
     */
    public static OssResult upload(InputStream inputStream, String path){
        return getExecutor().upload(inputStream,path);
    }

    /**
     * 文件上传
     *
     * @param inputStream  字节流
     * @param suffix       文件后缀
     * @return             文件上传结果
     */
    public  static OssResult uploadSuffix(InputStream inputStream, String suffix){
        return getExecutor().uploadSuffix(inputStream,suffix);
    }


    /**
     * 文件删除
     *
     * @param fileName  资源名称
     * @return  是否成功标识
     */
    public static boolean remove(String fileName){
        return getExecutor().remove(fileName);
    }

    /**
     * 获取OSS渠道
     *
     * @return OSS渠道
     */
    private static OssStorageService getExecutor() {
        int size = executorPool.size();
        OssStorageService executor;
        if (size < 1) {
            log.warn("OSS文件上传失败：无可用的渠道");
            throw new ToolkitOssException("上传失败：无可用的渠道");
        }
        if (size == 1) {
            executor = executorPool.get(0);
        } else {
            Random random = new Random();
            int n = random.nextInt(size);
            executor = executorPool.get(n);
        }
        return executor;
    }

    /**
     * 获取发送渠道
     *
     * @return 发送渠道
     */
    private static OssStorageService getExecutor(String channelCode) {
        if (!isBlank(channelCode)) {
            int size = executorPool.size();
            OssStorageService executor = null;
            if (size > 0) {
                for (OssStorageService executorItem : executorPool) {
                    if (executorItem.getChannelCode().equals(channelCode)) {
                        executor = executorItem;
                        break;
                    }
                }
            }
            if (null == executor) {
                log.warn("OSS文件上传失败：无可用的渠道");
                throw new ToolkitOssException("上传失败：无可用的渠道");
            }
            return executor;
        } else {
            return getExecutor();
        }
    }

    public static boolean isBlank(final CharSequence cs) {
        int strLen;
        if (cs == null || (strLen = cs.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(cs.charAt(i))) {
                return false;
            }
        }
        return true;
    }


}
